package com.study.java._01generic;

import java.util.Arrays;
import java.util.List;

/**
 * <pre>
 *     author : slx
 *     time   : 2020/11/17
 *     desc   : 通配符 "?"，扩大兼容分为
 *          泛型类之间没有任何关联，即使他们的类型有关联。
 *          可以通过通配符在类型之间建立关联
 *
 *          List<?> 会进行类型检测，List不进行类型检测
 *
 *     PESC原则：只取数据使用<? extends T>,只写数据使用<? super T>,
 *              如果可读可写使用<T> 具体类型
 * </pre>
 */
public class _03Demo {

    public static void main(String[] args) {
        List<String> sList = Arrays.asList("a", "b");
        // 编译报错因为printList接收List<Object>传入List<String>不匹配
        // printList(sList);
        // 编译通过，参数类型为List<?>,但是此时不能使用<>类型中的方法了
        printList1(sList);
    }

    // 类型上限，只读不可写,消费者
    public void add1(List<? extends Integer> list) {
        // 不能写入数据，编译报错
        //list.add(1);
        // 可以读数据
        System.out.println(list.get(0));
    }

    // 类型下线，只写不可读，生产者
    public void add2(List<? super Integer> list) {
        list.add(1);

        // 读数据，编译报错
        Integer object = (Integer) list.get(0);
    }

    // List<?> List<Object>：前者可以接受Null值插入列表，而后者不可
    // List<?> 无界通配符
    public void test3(List<?> l1, List<Object> l2) {
        System.out.println(l1.size());
        // 编译报错，使用了<?> 之后，l1则不能使用针针对参数T的方法，一般用于类中
        // 不依赖T的场所，例如Class<?>
        //l1.add("xx");
    }

    // 类型限定的用处
    public static void printList(List<Object> objects) {

    }

    public static void printList1(List<?> obejects) {
        // 上面方法虽然不通用，但是可以使用<Object>的方法
        // 而该方法虽然通用，但是不能使用<?>的方法，常用于不依赖<?>的方法，例如获取size等
        // 这也是为什么经常有Class<?>的原因
    }
}

